#pragma once

#include <map>
/**
Implements a variable dictionary that can contain any type of variable. Throws Error exceptions if any
errors occure
**/
class VariableList{
public:
	template<typename T>
	void add(const char *name,T *varinst){
		std::map<std::string,dictvar_t>::iterator it=vars.find(name);
		if(it!=vars.end()){
			(*it).second.ptr=varinst;
			(*it).second.type=typeid(T).name();
		}
		else{
			dictvar_t v;
			v.ptr=varinst;
			v.type=typeid(T).name();
			vars.insert(std::pair<std::string,dictvar_t>(std::string(name),v));
		}
	}
	template<typename T>
	void set(const char *name,const T &var){
		std::map<std::string,dictvar_t>::iterator it=vars.find(name);
		if(it==vars.end())
			throw Error("Not found!");
		//set the var to the value if its of the same type
		if((*it).second.type!=typeid(var).name())
			throw Error("Incompatible types!");
		*(T*)(*it).second.ptr=var;
	}

	template<typename T>
	T& get(const char *name){
		std::map<std::string,dictvar_t>::iterator it=vars.find(name);
		if(it==vars.end())
			throw Error("Not found!",name);
		if((*it).second.type!=typeid(T).name())
			throw Error("Incompatible types!");
		return *(T*)(*it).second.ptr;
	}
private:
	class dictvar_t{
	public:
		const char *type;
		void *ptr;
	};
	std::map<std::string,dictvar_t>	vars;
};
